package DBAccess;

use MooseX::Singleton;
use Log;
use DBI;

has 'filename' => (
    is => 'rw',
    isa => 'Str',
    default => '',
    );

has 'dbh' => (
    is => 'rw',
    isa => 'Item',
    init_arg => undef,
    );
has 'opened' => (
    is => 'rw' ,
    isa => 'Bool',
    default => 0,
    init_arg => undef,
    );

sub open {
    my $s=shift;
    if(!$s->opened) {
	$s->dbh(DBI->connect("dbi:SQLite:dbname=".$s->filename,"",""));
	if(!defined($s->dbh)) {
	    my $l=Log->instance;
	    $l->xsupererror("fb86a42a-0423-33b0-aead-dc7f5024637c",
			$l->format($s->filename,'open',"cannot connect: ".$DBI::errstr));	
	    
	}else{
	    $s->opened(1);
	}
    }else{
	my $l=Log->instance;
	$l->xsupererror("081b7884-1991-3da0-9070-dd78a49e8661",
			$l->format($s->filename,'open',"file alredy opened"));	
    }
}


sub close {
    my $s=shift;
    if($s->opened) {
	$s->dbh->disconnect;
	$s->dbh(undef);
	$s->opened(0);
    }else{
	my $l=Log->instance;
	$l->xsupererror("4e5e5b6b-7e71-3002-a12b-cf1de9ab3f46",
			$l->format($s->filename,'close',"cannot close db (already closed?)"));	
    }
}

sub remove {
    my $s=shift;
    my $l=Log->instance;
    if(!$s->opened) {
	unlink($s->filename) ||
	    $l->xsupererror("8dfd438b-7905-3e88-9e27-d8c6d76d50d7",
			    $l->format($s->filename,'remove',"cannot remove db file"));
    }else{
	$l->xsupererror("b34255ce-1aeb-3414-9d6b-75a1a93220f2",
			$l->format($s->filename,'remove',"cannot remove due DB is opened"));	
    }
}


sub do {
    my $s = shift;
    my $stm = shift;
    if(!$s->opened) {
	my $l=Log->instance;
	$l->xsupererror("2e6bfbc6-9e8a-36c4-9520-1b453d268ac4",
			$l->format($s->filename,'do',"db not opened"));
    }
    my $ret = $s->dbh->do($stm);
    unless($ret) {
	my $l=Log->instance;
	$l->xsupererror("1b1bcd4a-6add-33ee-a090-4df809844b3e",
			$l->format($s->filename,'do',$s->dbh->errstr));
    }
    return $ret;
}


sub exec_query {
    my $s = shift;
    my $query = shift;
    my @params = @_;
    my $l=Log->instance;
    if(!$s->opened) {
	$l->xsupererror("de896a5c-e6e5-3e89-9281-c6b37214d46a",
			$l->format($s->filename,'do',"db not opened"));
    }

    $l->xdebug(3,"16b520bc-42ab-329f-8f6b-ceff22d15d44",
	       $l->format($s->filename,'exec_query',"'$query' params: @params"));

    my $query_handle = $s->dbh->prepare($query);
    $query_handle->execute();
 
# Instead of simply fetching rows I prefer, for each one,
# to assign values to predefinite values.
# Bind columns is a wonderful function!

    my @refs= map { \my $x } @params;
#    print Dumper(@refs);
    my $res = [];
    $query_handle->bind_columns(@refs);
    while($query_handle->fetch()) {
	my $record = {};
#	print Dumper(@refs)."---";
	my $i=0;
	foreach (@params)  { 
	    my $ref=$refs[$i++];
#	    print Dumper($ref);
	    $record->{$_}=$$ref; 
	} 
	push(@$res,$record);
    }

#    print Dumper($res);
 
# Close connection
    $query_handle->finish;

    return $res;

}

sub smart_select {
    my $self=shift;
    my $complex_sql = shift;
    unless ( $complex_sql =~ /\{([\w,]+)\}/o ) {
	my $l=Log->instance;
	$l->xinternal("da848d1c-81e9-3284-b6c4-887266bd0417",
		      $l->format($self->filename,'smart_select',"format invalid for $complex_sql"));
    }
    my $fs=$1;
    my @f = split( /,/,$fs);
    $complex_sql =~ s/\{//o;
    $complex_sql =~ s/\}//o;

    return $self->exec_query($complex_sql,@f);
}



no Moose;
__PACKAGE__->meta->make_immutable;

